package opentelemetry

import (
	"go.opentelemetry.io/otel"
	"go.opentelemetry.io/otel/attribute"
	"go.opentelemetry.io/otel/propagation"
	"go.opentelemetry.io/otel/trace"
	"my_framework/web"
)

const instrumentationName = "my_framework/middlewares/opentelemetry"

type MiddlewareBuilder struct {
	Tracer trace.Tracer
}

//func NewMiddlewareBuilder(tracer trace.Tracer) *MiddlewareBuilder {
//	return &MiddlewareBuilder{tracer}
//}

func (m MiddlewareBuilder) Build() web.Middleware {
	if m.Tracer == nil {
		m.Tracer = otel.GetTracerProvider().Tracer(instrumentationName)
	}
	return func(next web.HandleFunc) web.HandleFunc {
		return func(ctx *web.Context) {
			reqCtx := ctx.Req.Context()
			// 尝试和客户端的trace结合
			reqCtx = otel.GetTextMapPropagator().Extract(reqCtx, propagation.HeaderCarrier(ctx.Req.Header))

			// 创建span,这里的spanName(参数2)应该是命中的路由名称,但是现在还不知道
			reqCtx, span := m.Tracer.Start(reqCtx, "unknown")
			defer span.End()

			// 根据业务自己加
			span.SetAttributes(attribute.String("http.method", ctx.Req.Method))
			span.SetAttributes(attribute.String("http.url", ctx.Req.URL.String()))
			// schema -> http/https
			span.SetAttributes(attribute.String("http.schema", ctx.Req.URL.Scheme))
			span.SetAttributes(attribute.String("http.host", ctx.Req.Host))

			// reqCtx创建完trace,复制给ctx.Req的ctx
			// 复制的操作耗性能,但是为了使用该ctx,没办法
			ctx.Req = ctx.Req.WithContext(reqCtx)

			// 下一步
			next(ctx)
			// 执行完next,才有值
			span.SetName(ctx.MatchedRoute)
			// 响应码
			span.SetAttributes(attribute.Int("http.status", ctx.RespStatusCode))
		}
	}
}
